﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SmartMathLibrary.Transformation
{
    /// <summary>
    /// The affintransformation includes the translation, rotation and scaling of all three axis.
    /// </summary>
    [Serializable]
    public class AffinTransformation
    {
        /// <summary>
        /// The parameters for the transformation.
        /// </summary>
        private AffinTransformationParameters parameters;

        /// <summary>
        /// Initializes a new instance of the <see cref="AffinTransformation"/> class.
        /// </summary>
        /// <param name="parameters">The parameters for the transformation.</param>
        public AffinTransformation(AffinTransformationParameters parameters)
        {
            this.parameters = parameters;
        }

        /// <summary>
        /// Gets or sets the parameters for the transformation.
        /// </summary>
        /// <value>The parameters for the transformation.</value>
        public AffinTransformationParameters Parameters
        {
            get { return this.parameters; }
            set { this.parameters = value; }
        }

        /// <summary>
        /// Transforms the specified point into a new system, which is specified by the parameters.
        /// </summary>
        /// <param name="point">The point to transform.</param>
        /// <returns>The transformed point.</returns>
        public Point3D TransformPoint(Point3D point)
        {
            if (point == (Point3D) null)
            {
                throw new ArgumentNullException("point");
            }

            double newX = 0;
            double newY = 0;
            double newZ = 0;
            double x = point.X;
            double y = point.Y;
            double z = point.Z;

            newX = this.parameters.TranslationX + (1 + this.parameters.ScaleX) * x - this.parameters.RotationZ * y +
                   this.parameters.RotationY * z;
            newY = this.parameters.TranslationY + this.parameters.RotationZ * x + (1 + this.parameters.ScaleY) * y -
                   this.parameters.RotationX * z;
            newZ = this.parameters.TranslationZ - this.parameters.RotationY * x + this.parameters.RotationX * y +
                   (1 + this.parameters.ScaleZ) * z;

            return new Point3D(newX, newY, newZ);
        }
    }
}